package com.lizicloud.infrastructure.common.utils;

import java.io.PrintWriter;
import java.io.StringWriter;

/**
 * 异常处理工具类
 */
public class ExceptionUtils {
    
    /**
     * 获取异常的完整堆栈信息
     */
    public static String getStackTrace(Throwable throwable) {
        if (throwable == null) {
            return "";
        }
        
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        throwable.printStackTrace(pw);
        return sw.toString();
    }
    
    /**
     * 获取异常的简要信息
     */
    public static String getBriefMessage(Throwable throwable) {
        if (throwable == null) {
            return "";
        }
        
        return throwable.getClass().getSimpleName() + ": " + throwable.getMessage();
    }
    
    /**
     * 获取异常的根原因
     */
    public static Throwable getRootCause(Throwable throwable) {
        if (throwable == null) {
            return null;
        }
        
        Throwable cause = throwable.getCause();
        if (cause == null) {
            return throwable;
        }
        return getRootCause(cause);
    }
    
    /**
     * 获取异常的根原因消息
     */
    public static String getRootCauseMessage(Throwable throwable) {
        Throwable rootCause = getRootCause(throwable);
        if (rootCause == null) {
            return "";
        }
        return rootCause.getMessage();
    }
    
    /**
     * 包装异常
     */
    public static RuntimeException wrapException(String message, Throwable cause) {
        return new RuntimeException(message, cause);
    }
    
    /**
     * 包装异常（不带消息）
     */
    public static RuntimeException wrapException(Throwable cause) {
        return new RuntimeException(cause);
    }
    
    /**
     * 检查是否为业务异常
     */
    public static boolean isBusinessException(Throwable throwable) {
        if (throwable == null) {
            return false;
        }
        return throwable instanceof com.lizicloud.infrastructure.common.exception.BusinessException;
    }
    
    /**
     * 检查是否为系统异常
     */
    public static boolean isSystemException(Throwable throwable) {
        if (throwable == null) {
            return false;
        }
        return !isBusinessException(throwable);
    }
    
    /**
     * 检查异常是否包含指定类型
     */
    public static boolean containsExceptionType(Throwable throwable, Class<? extends Throwable> exceptionType) {
        if (throwable == null || exceptionType == null) {
            return false;
        }
        
        Throwable current = throwable;
        while (current != null) {
            if (exceptionType.isInstance(current)) {
                return true;
            }
            current = current.getCause();
        }
        return false;
    }
    
    /**
     * 获取异常链中指定类型的异常
     */
    @SuppressWarnings("unchecked")
    public static <T extends Throwable> T getExceptionOfType(Throwable throwable, Class<T> exceptionType) {
        if (throwable == null || exceptionType == null) {
            return null;
        }
        
        Throwable current = throwable;
        while (current != null) {
            if (exceptionType.isInstance(current)) {
                return (T) current;
            }
            current = current.getCause();
        }
        return null;
    }
    
    /**
     * 安全地抛出异常
     */
    public static <T extends Throwable> void sneakyThrow(Throwable throwable) throws T {
        throw (T) throwable;
    }
    
    /**
     * 忽略异常（记录日志但不抛出）
     */
    public static void ignoreException(Runnable runnable) {
        try {
            runnable.run();
        } catch (Exception e) {
            LogUtils.warn("忽略的异常: " + getBriefMessage(e));
        }
    }
    
    /**
     * 忽略异常（带返回值）
     */
    public static <T> T ignoreException(Supplier<T> supplier, T defaultValue) {
        try {
            return supplier.get();
        } catch (Exception e) {
            LogUtils.warn("忽略的异常: " + getBriefMessage(e));
            return defaultValue;
        }
    }
    
    /**
     * 重试操作
     */
    public static <T> T retryOperation(Supplier<T> supplier, int maxRetries, long delayMillis) {
        Exception lastException = null;
        
        for (int i = 0; i <= maxRetries; i++) {
            try {
                return supplier.get();
            } catch (Exception e) {
                lastException = e;
                LogUtils.warn("操作失败，第%d次重试: %s", i + 1, getBriefMessage(e));
                
                if (i < maxRetries && delayMillis > 0) {
                    try {
                        Thread.sleep(delayMillis);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw wrapException("重试被中断", ie);
                    }
                }
            }
        }
        
        throw wrapException("操作失败，已重试" + maxRetries + "次", lastException);
    }
    
    /**
     * 重试操作（无返回值）
     */
    public static void retryOperation(Runnable runnable, int maxRetries, long delayMillis) {
        retryOperation(() -> {
            runnable.run();
            return null;
        }, maxRetries, delayMillis);
    }
    
    /**
     * 转换异常为字符串（安全模式）
     */
    public static String toStringSafe(Throwable throwable) {
        if (throwable == null) {
            return "null";
        }
        
        try {
            return getBriefMessage(throwable);
        } catch (Exception e) {
            return "Exception in toString: " + e.getMessage();
        }
    }
    
    /**
     * 函数式接口：供应商
     */
    @FunctionalInterface
    public interface Supplier<T> {
        T get() throws Exception;
    }
    
    private ExceptionUtils() {
        // 私有构造函数，防止实例化
    }
}